package yawning.mew.equipment;

import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import yawning.mew.equipment.RawItem.Property;

public class WowheadItemSource extends ItemSource {
	private static String SOCKET_BONUS = ">Socket Bonus: +";
	SAXBuilder mBuilder = new SAXBuilder();
	
	private static Map<String,Property> sPropertyMap;
	private static Map<String,Property> sSocketMap;

	static {
		sSocketMap = new HashMap<String,Property>();

		sSocketMap.put("Agility", Property.AGILITY);
		sSocketMap.put("Critical Strike Rating", Property.CRIT_RATING);
		sSocketMap.put("Resilience Rating", Property.RESILIENCE_RATING);

		sPropertyMap = new HashMap<String,Property>();

		sPropertyMap.put("slotbak", Property.SLOT);
		sPropertyMap.put("armor", Property.ARMOR);
		sPropertyMap.put("itemset", Property.ITEM_SET);
		
		sPropertyMap.put("sta", Property.STAMINA);
		sPropertyMap.put("agi", Property.AGILITY);
		sPropertyMap.put("str", Property.STRENGTH);
		sPropertyMap.put("int", Property.INTELLECT);
		sPropertyMap.put("spi", Property.SPIRIT);
		sPropertyMap.put("hastertng", Property.HASTE_RATING);
		sPropertyMap.put("critstrkrtng", Property.CRIT_RATING);
		sPropertyMap.put("hitrtng", Property.HIT_RATING);
		sPropertyMap.put("exprtng", Property.EXPERTISE_RATING);
		sPropertyMap.put("atkpwr", Property.ATTACK_POWER);
		sPropertyMap.put("resirtng", Property.RESILIENCE_RATING);
		
		sPropertyMap.put("nsockets", Property.NUM_SOCKETS);
		sPropertyMap.put("socket1", Property.SOCKET1);
		sPropertyMap.put("socket2", Property.SOCKET2);
		sPropertyMap.put("socket3", Property.SOCKET3);
		sPropertyMap.put("socketbonus", null);
		
		sPropertyMap.put("mledmgmin", Property.MELEE_DMG_MIN);
		sPropertyMap.put("mledmgmax", Property.MELEE_DMG_MAX);
		sPropertyMap.put("mledps", Property.MELEE_DPS);
		sPropertyMap.put("mlespeed", Property.MELEE_SPEED);
		
		// Ignored properties from wowhead
		sPropertyMap.put("sellprice", null);
		sPropertyMap.put("displayid", null);
		sPropertyMap.put("maxcount", null);
		sPropertyMap.put("feratkpwr", null);
		sPropertyMap.put("dura", null);
		sPropertyMap.put("avgbuyout", null);
		sPropertyMap.put("buyprice", null);
		sPropertyMap.put("cooldown", null);

		// Will these every be different from the MELEE_* ones?
		sPropertyMap.put("dps", null);
		sPropertyMap.put("dmgmin1", null);
		sPropertyMap.put("dmgmax1", null);
		sPropertyMap.put("dmgtype1", null);
		sPropertyMap.put("speed", null);
		
		// Maybe needed for requirements check
		sPropertyMap.put("reqskillrank", null);
		sPropertyMap.put("reqskill", null);
		sPropertyMap.put("reqrep", null);
		sPropertyMap.put("reqlevel", null);
		sPropertyMap.put("classes", null);
		sPropertyMap.put("reqfaction", null);
		sPropertyMap.put("reqarenartng", null);
		sPropertyMap.put("races", null);
	}
	
	@Override
	public RawItem getById(int id) {
		try {
			RawItem item = new RawItem();
			
			URL url = new URL("http://www.wowhead.com/item=" + id + "&xml");
			Document doc = mBuilder.build(url);
			Element root = doc.getRootElement();
			Element element = root.getChild("item"); 
			item.name = element.getChildText("name");
			item.id = id;
			
			item.properties.put(Property.QUALITY, Integer.parseInt(element.getChild("quality").getAttributeValue("id")));
			item.properties.put(Property.CLASS, Integer.parseInt(element.getChild("class").getAttributeValue("id")));
			item.properties.put(Property.SUBCLASS, Integer.parseInt(element.getChild("subclass").getAttributeValue("id")));
	
			// Check for socket bonus
			String htmlTooltip = element.getChildText("htmlTooltip");
			int offset = htmlTooltip.indexOf(SOCKET_BONUS);
			if (offset > 0) {
				offset += SOCKET_BONUS.length();
				int offset2 = htmlTooltip.indexOf(' ', offset);
				int bonus = Integer.parseInt(htmlTooltip.substring(offset, offset2));
				offset = htmlTooltip.indexOf('<', offset);
				String stat = htmlTooltip.substring(offset2 + 1, offset);
				if (sSocketMap.containsKey(stat)) {
					item.properties.put(Property.SOCKET_BONUS_STAT, sSocketMap.get(stat).ordinal());
					item.properties.put(Property.SOCKET_BONUS_VALUE, bonus);
				}
				else System.out.println("** WowheadItemSource: Socket Bonus \"" + stat + "\" not yet supported");
			}
			
			JSONObject jso = (JSONObject)JSONValue.parse("{" + element.getChildText("jsonEquip") + "}");
			@SuppressWarnings("unchecked") Set<Map.Entry<Object,Object>> set = jso.entrySet();
			for (Map.Entry<Object,Object> i : set) {
				String k = i.getKey().toString();
				Number n = (Number)i.getValue();
				if (sPropertyMap.containsKey(k)) {
					Property p = sPropertyMap.get(k);
					if (p != null) item.properties.put(p, n.intValue());
				}
				else System.out.println("** WowheadItemSource: Property " + k + " not yet supported");
			}
			return item;
		}
		catch (Exception e) {
			sExceptions.append(e.toString());
			if (mNext != null) return mNext.getById(id);
			else return null;
		}
	}
}
